On Windows 11, in File Explorer, gtk-picture.exe has Windows’ default icon for an executable file and GTK4’s default icon in the task bar when running:


I wanted to customise these icons. Also, I wanted a similar icon to appear in the application’s window’s header bar, to the left.
*.res file
The icon can be set by linking an appropriate *.res (resource) file. In my case, the file was haskell-logo.res. The file is linked by specifying the GHC option -optl. For example:
|
1 2 3 4 5 6 7 8 9 10 11 |
executables: gtk-picture: main: Main.hs source-dirs: app generated-other-modules: Paths_gtk_picture ghc-options: - -threaded - -rtsopts - -with-rtsopts=-N - -optl-mwindows - -optl=haskell-logo.res |
*.rc file
A *.res file is created by compiling an appropriate *.rc (resource script) file with the windres application. That application is provided by the MSYS2 package mingw-w64-x86_64-binutils. It acts like the Windows Resource Compiler. For example:
|
1 |
stack exec -- windres --input haskell-logo.rc --output-format coff --output haskell-logo.res |
The *.rc file specifies the icon. For example:
|
1 |
IDI_ICON1 ICON "haskell-logo.ico" |
IDI_ICON1 is an identifier for the resource. By convention, the initial IDI indicates that the resource is an icon or bitmap. ICON identifies the resource type as an icon. The type is followed by the path to the resource, in this case a *.ico (Windows icon) file.
*.ico file
An *.ico file stores one or more icon images of different sizes. It can be created from a *.svg file with the ImageMagick application. For example:
|
1 |
magick -background none haskell-logo.svg -define icon:auto-resize haskell-logo.ico |
It is important to specify -background none before the input *.svg file is specified, otherwise the background will be white.
I used the 2009 Thompson-Wheeler logo, resized in InkScape to be 256 px x 256 px:
gtk-picture.exe
The end result was as desired: in File Explorer, gtk-picture.exe had the specified icon and the same icon in the task bar when running:


For an icon in the application’s header bar, the solution was for the ApplicationWindow value to specify a HeaderBar value as its titleBar and for an appropriate Image value to be packed at the start of that header bar, as follows:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
activate :: Gtk.Application -> IO () activate app = do ... image <- iconImage headerBar <- new Gtk.HeaderBar [] #packStart headerBar image window <- new Gtk.ApplicationWindow [ #application := app , #title := "Clicking on a picture" , #titlebar := headerBar , #child := grid ] window.show iconFile :: IO FilePath iconFile = getDataFileName "haskell-logo24x24.png" iconImage :: IO Gtk.Image iconImage = iconFile >>= Gtk.imageNewFromFile |
A 24 px square image seemed an appropriate size. If the titleWidget of a HeaderBar is not set, it displays the title of the window that it is contained in. The default showTitleButtons of a HeaderBar is True.
